
package member
import (
    "fmt"
    "time"
	"github.com/astaxie/beego/orm"
	"strings"
	"errors"
	"dhfshop/models"
	"dhfshop/models/misc"
	"dhfshop/models/consts"
	"github.com/satori/go.uuid"
	"dhfshop/models/org"
	"wxsdk/oauth"
	"unicode/utf8"
	"dhfshop/utils/helper"
)

type MemberValue struct {
	MemberId        int64   `orm:"column(member_id);pk" json:"member_id" form:"member_id"`        //注意字段不一致的问题user_id
    //PartnerId       int64      `orm:"column(partner_id);index" json:"partner_id" form:"partner_id"` //由cust_account表动态绑定的,不能静态绑定
	AppId           string   `orm:"column(app_id);size(32);index" json:"app_id"`                           //所属appid
	MemberName      string  `orm:"column(user_name);size(64);unique" json:"user_name" form:"user_name"`    //只所以不存储微信nickname，避免和已有账号重复
	Password        string  `orm:"-" json:"-" form:"password"`
	PasswordConfirm string  `orm:"-" json:"-" form:"password_confirm"`
	PwdHashed  string  `orm:"column(pwd_hashed)" json:"-"`
	Salt       string  `orm:"column(salt)" json:"-"`
	Name       string  `orm:"column(name);size(190);index" json:"name" form:"name"`  // 姓名,也用做存储微信nickname 
	Exp        int     `orm:"column(exp)" json:"exp" form:"exp"`                     //经验值
	Level      int     `orm:"column(level)" json:"level" form:"level"`               // 等级
	Sex        int     `orm:"column(sex)" json:"sex" form:"sex"`                     //也用做存储微信sex 
	Avatar     string  `orm:"column(avatar)" json:"avatar" form:"avatar"`            // 用户头像,也用做存储微信头像
	BirthDay        time.Time `orm:"column(birthday);type(datetime);null" json:"-" form:"-"` /*  */
    BirthDayStr     string  `orm:"-" json:"birthday,omitempty" form:"birthday"`
	Phone           string  `orm:"column(phone)" json:"phone" form:"phone"`       // 
	Address         string  `orm:"column(address)" json:"address" form:"address"`       // 
	Qq              string  `orm:"column(qq)" json:"qq" form:"qq"`       // 
	Email           string  `orm:"column(email)" json:"email" form:"email"`       // 
	RegFrom         string  `orm:"column(reg_from)" json:"reg_from" form:"reg_from"`       // 
	RegIp           string  `orm:"column(reg_ip)" json:"reg_ip" form:"reg_ip"`       // 
	State           int     `orm:"column(state)" json:"state" form:"state"`       //
    RegTime         int64   `orm:"column(reg_time)" json:"reg_time" form:"reg_time"` 
	LastLoginTime   int64   `orm:"column(last_login_time)" json:"last_login_time" form:"last_login_time"` 
	UpdateTime      int64   `orm:"column(update_time)" json:"update_time" form:"update_time"`
	DynamicToken    string  `orm:"column(dynamic_token)" json:"dynamic_token" form:"dynamic_token"`   // 动态令牌，用于登陆或API调用
    TimeoutTime     int64   `orm:"column(timeout_time)" json:"timeout_time" form:"timeout_time"`    //超时时间 
	Client          string  `orm:"column(client)" json:"client" form:"client"`   // 客户端类型(android wap ios wechat windows)
	LoginMode       int     `orm:"column(login_mode);default(1)" json:"login_mode" form:"login_mode"`  //登陆方式：1 自账号登陆; 2 微信登陆
	InviterId       int64   `orm:"column(inviter_id)" json:"inviter_id" form:"inviter_id"`  //推荐人
	// 微信登陆用户信息
	OpenID          string   `orm:"column(open_id);size(190);index" json:"open_id"`
	Province        string   `orm:"column(province)" json:"province"`       //省
	City            string   `orm:"column(city)" json:"city"`               //城市
	Country         string   `orm:"column(country)" json:"country"`         //国家
	Unionid         string   `orm:"column(unionid);size(190);index" json:"unionid"`   //相同开发账号下多个公众号的用户唯一ID
    SessionKey      string   `orm:"column(session_key)" json:"session_key"` //
	Privilege       string   `orm:"column(privilege);type(text)" json:"privilege"` //
	IsSubScribe     bool     `orm:"column(is_subscribe);default(false)" json:"is_subscribe" form:"is_subscribe"` //
    LoginStoreId    int64    `orm:"column(login_store_id)" json:"login_store_id" form:"login_store_id"`  //登陆店铺编号
	Remark          string   `orm:"column(remark)" json:"remark" form:"remark"`   //备注
}

func init() {
    orm.RegisterModel(new(MemberValue))   
}

// 创建会员
func CreateMember(partnerId int64, userName, password string) (memberId int64, err error) {
	member := new(MemberValue)
	member.MemberId, _ = misc.GetUserNo()
	//member.PartnerId = partnerId
	member.MemberName = userName
	member.Password = password
	member.Salt = uuid.NewV4().String()
	if member.Password == "" {
		member.Password = strings.ToLower(member.MemberName)
	}
	member.PwdHashed = org.EncryptPassword(member.Salt, member.Password)
	_, err = addMember(member)
	memberId = member.MemberId
	// init account
	account := new(Account)
	account.MemberId = member.MemberId
	//account.PartnerId = member.PartnerId
	account.Integral = 0
	account.FreezeIntegral = 0
	account.Balance = 0.0
	account.FreezeBalance = 0.0
	account.ExpiredBalance = 0.0
	account.Present = 0.0
	account.FreezePresent = 0.0
	account.ExpiredPresent = 0.0
	account.TotalPresent = 0.0
	account.TotalConsume = 0.0
	account.TotalCharge = 0.0
	account.TotalPay = 0.0
	account.PriorityPay = 1
	_, err = AddAccount(account)
	return
}

// 基于小程序或者公众号创建微信会员
func CreateWeChatMember(appId, usefulId string, weChatUser *oauth.BuyerUserInfo, inviterId int64) (memberId int64, err error) {
	member := new(MemberValue)
	//member.PartnerId = partnerId
	member.MemberId, _ = misc.GetUserNo()
	member.MemberName = usefulId
	member.Password = usefulId
	member.Salt = uuid.NewV4().String()
	if member.Password == "" {
		member.Password = strings.ToLower(member.MemberName)
	}
	member.PwdHashed = org.EncryptPassword(member.Salt, member.Password)
	member.AppId = appId
	member.InviterId = inviterId
	member.OpenID = weChatUser.OpenID
	member.Name = FilterEmoji(weChatUser.Nickname)
	member.Sex = weChatUser.Gender
	member.Avatar = weChatUser.AvatarURL
	member.Province = weChatUser.Province
	member.City = weChatUser.City
	member.Country = weChatUser.Country
	member.Unionid = weChatUser.Unionid
	if len(weChatUser.SessionKey) > 0 {
	   member.SessionKey = weChatUser.SessionKey
	}
	if len(weChatUser.Headimgurl) > 0 {    //公众号特有字段单独判断
	    member.Sex = weChatUser.Sex
	    member.Avatar = weChatUser.Headimgurl
	    if len(weChatUser.Privilege) > 0 {
	      member.Privilege = strings.Join(weChatUser.Privilege, ",")
	    }
	    if weChatUser.Subscribe == 1 {
	       member.IsSubScribe = true
	    }else{
	       member.IsSubScribe = false
	    }
	}
	_, err = addMember(member)
	memberId = member.MemberId
	// init account
	account := new(Account)
	account.MemberId = member.MemberId
	//account.PartnerId = member.PartnerId
	account.AppId = appId
	account.Integral = 0
	account.FreezeIntegral = 0
	account.Balance = 0.0
	account.FreezeBalance = 0.0
	account.ExpiredBalance = 0.0
	account.Present = 0.0
	account.FreezePresent = 0.0
	account.ExpiredPresent = 0.0
	account.TotalPresent = 0.0
	account.TotalConsume = 0.0
	account.TotalCharge = 0.0
	account.TotalPay = 0.0
	account.PriorityPay = 1
	_, err = AddAccount(account)
	return
}

// 创建微信小程序基本会员
func CreateBasicWeChatMember(appId, usefulId string, weChatUser *oauth.SessionInfo, inviterId int64) (memberId int64, err error) {
	member := new(MemberValue)
	//member.PartnerId = partnerId
	member.MemberId, _ = misc.GetUserNo()
	member.MemberName = usefulId
	member.Password = usefulId
	member.Salt = uuid.NewV4().String()
	if member.Password == "" {
		member.Password = strings.ToLower(member.MemberName)
	}
	member.PwdHashed = org.EncryptPassword(member.Salt, member.Password)
	member.AppId = appId
	member.InviterId = inviterId
	member.OpenID = weChatUser.OpenId
	member.Unionid = weChatUser.UnionId
	member.SessionKey = weChatUser.SessionKey
	_, err = addMember(member)
	memberId = member.MemberId
	// init account
	account := new(Account)
	account.MemberId = member.MemberId
	//account.PartnerId = member.PartnerId
	account.AppId = appId
	account.Integral = 0
	account.FreezeIntegral = 0
	account.Balance = 0.0
	account.FreezeBalance = 0.0
	account.ExpiredBalance = 0.0
	account.Present = 0.0
	account.FreezePresent = 0.0
	account.ExpiredPresent = 0.0
	account.TotalPresent = 0.0
	account.TotalConsume = 0.0
	account.TotalCharge = 0.0
	account.TotalPay = 0.0
	account.PriorityPay = 1
	_, err = AddAccount(account)
	return
}

func addMember(m *MemberValue) (id int64, err error) {
	o := models.GetDefaultDB()
	id, err = o.Insert(m)
	return
}

func GetMemberById(id int64) (v *MemberValue, err error) {
	o := models.GetDefaultDB()
	v = &MemberValue{MemberId: id}
	if err = o.Read(v); err == nil {
		v.BirthDayStr = v.BirthDay.Format(consts.DATETIME_FORMAT)
		return v, nil
	}
	return nil, err
}

//查询会员，可选条件：ID、用户名、手机号码、
func GetMemberValue(query map[string]string)(ad *MemberValue,err error) {
	o := models.GetDefaultDB()
	qs := o.QueryTable(new(MemberValue))
	for k, v := range query {
		k = strings.Replace(k, ".", "__", -1)
		qs = qs.Filter(k, v)	
	}
	if err = qs.One(ad); err == nil {
		ad.BirthDayStr = ad.BirthDay.Format(consts.DATETIME_FORMAT)
		return ad, nil
	}
	return nil, err
}

func GetAllMembers(appIds []string,query map[string]string,fields []string,order_by map[string]string,offset int,limit int)([]*MemberValue,int64,error){
	o := models.GetDefaultDB()
	qs := o.QueryTable(new(MemberValue))
	for k, v := range query {
		k = strings.Replace(k, ".", "__", -1)
		if ok := strings.Contains(v, "|"); ok {
		    valueArr := strings.Split(v, "|")
			qs = qs.Filter(k, valueArr)
		}else{
		    qs = qs.Filter(k, v)
		}	
	}
	if len(appIds) > 0 {
        qs = qs.Filter("app_id__in", appIds)
    }
	cnt, err := qs.Count()
	// order by:
	var sortFields []string
	for k, v := range order_by {
		orderby := ""
		if v == "desc" {
			orderby = "-" + k
		} else if v == "asc" {
			orderby = k
		} else {
			return nil, 0, errors.New("Error: Invalid order. Must be either [asc|desc]")
		}
		sortFields = append(sortFields, orderby)
	}
	qs = qs.OrderBy(sortFields...)
	var lists []*MemberValue
	if _, err = qs.Limit(limit, offset).All(&lists, fields...); err == nil {
		for _, member := range lists {
		    member.BirthDayStr = member.BirthDay.Format(consts.DATETIME_FORMAT)
		}
		return lists, cnt, nil
	}
	return nil, 0, err
}

func GetMemberByUsr(username string) (member *MemberValue, err error) {
	o := models.GetDefaultDB()
	member = &MemberValue{MemberName:username}   //多个的话,read中需要指明列
	if err = o.Read(member,"MemberName"); err != nil {
		return member, err
	}
	member.BirthDayStr = member.BirthDay.Format(consts.DATETIME_FORMAT)
	return member, nil
}

func GetMemberByOpenId(openId string) (member *MemberValue, err error) {
	o := models.GetDefaultDB()
	member = &MemberValue{OpenID:openId}   //多个的话,read中需要指明列
	if err = o.Read(member,"OpenID"); err != nil {
		return member, err
	}
	member.BirthDayStr = member.BirthDay.Format(consts.DATETIME_FORMAT)
	return member, nil
}

func GetMemberByIdOrOpenId(memberId, openId string) (member *MemberValue, err error) {
	member = &MemberValue{}
	o := models.GetDefaultDB()
	qs := o.QueryTable(new(MemberValue))
	if len(memberId) > 0 {
	    qs = qs.Filter("member_id", memberId)
	}
	if len(openId) > 0 {
	    qs = qs.Filter("open_id", openId)
	}
	if err = qs.One(member); err == nil {
	    member.BirthDayStr = member.BirthDay.Format(consts.DATETIME_FORMAT)
	}
	return
}

func GetMemberIdByOpenId(openId string) (member *MemberValue, err error) {
	member = &MemberValue{}
	o := models.GetDefaultDB()
	err = o.QueryTable(new(MemberValue)).Filter("open_id", openId).OrderBy("-member_id").One(member)
	return
}

func GetMemberIdByUnionid(appId, unionid string) (member *MemberValue, err error) {
	o := models.GetDefaultDB()
	member = &MemberValue{AppId:appId, Unionid:unionid}   //多个的话,read中需要指明列
	if err = o.Read(member,"AppId","Unionid"); err != nil {
		return member, err
	}
	member.BirthDayStr = member.BirthDay.Format(consts.DATETIME_FORMAT)
	return member, nil
}

// 更新会员
func UpdateMemberById(m *MemberValue, k ...string) (err error) {
	o := models.GetDefaultDB()
	v := MemberValue{MemberId: m.MemberId}
	if err = o.Read(&v); err == nil {
		if _, err = helper.Contains("name", k); err == nil {
		   if len(m.Name) > 0 {
		      m.Name = FilterEmoji(m.Name)
		   }
		}
		if _, err = o.Update(m, k...); err != nil {
			return err
		}
	}
	return
}

func UpdateMemberStateById(memberId int64, state int) (err error) {
	o := models.GetDefaultDB()
	m := new(MemberValue)
	v := MemberValue{MemberId: memberId}
	if err = o.Read(&v); err == nil {
		m.MemberId = memberId
		m.State = state
		if _, err = o.Update(m, "state"); err != nil {
			return
		}
	}
	return
}

func UpdateMemberByOpenId(m *MemberValue, k ...string) (err error) {
	o := models.GetDefaultDB()
	v := MemberValue{OpenID: m.OpenID}
	if err = o.Read(&v, "OpenID"); err == nil {
		m.MemberId = v.MemberId
		if _, err = helper.Contains("name", k); err == nil {
		   if len(m.Name) > 0 {
		      m.Name = FilterEmoji(m.Name)
		   }
		}
		if _, err = o.Update(m, k...); err != nil {
			return err
		}
	}
	return
}

func UpdateMemberByUnionId(m *MemberValue, k ...string) (err error) {
	o := models.GetDefaultDB()
	v := MemberValue{Unionid: m.Unionid}
	if err = o.Read(&v, "Unionid"); err == nil {
		m.MemberId = v.MemberId
		if _, err = helper.Contains("name", k); err == nil {
		   if len(m.Name) > 0 {
		      m.Name = FilterEmoji(m.Name)
		   }
		}
		if _, err = o.Update(m, k...); err != nil {
			return err
		}
	}
	return
}

func DeleteMemberById(id int64) (err error) {
	o := models.GetDefaultDB()
	v := MemberValue{MemberId: id}
	if err = o.Read(&v); err == nil {
		var num int64
		if num, err = o.Delete(&v); err == nil {
			fmt.Println("Number of records deleted in database:", num)
		}
	}
	return
}

type RepeatData struct {
	OpenId  string   
	Number  int    
}

func GetRepeatData() (repeatDatas []*RepeatData, err error) {
	sql := `SELECT open_id, COUNT(*) AS number FROM member_value GROUP BY open_id HAVING COUNT(*) >=2`
	o := models.GetDefaultDB()					
	_, err = o.Raw(sql).QueryRows(&repeatDatas)
	return
}

//过滤emoji表情 
func FilterEmoji(content string) string { 
   new_content := "" 
   for _, value := range content {
      _, size := utf8.DecodeRuneInString(string(value)) 
	  if size <= 3 { 
	      new_content += string(value) 
	  } 
	} 
	return new_content 
}

